package com.zimi.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zimi.mapper.SysRoleMapper;
import com.zimi.mapper.SysRolePrivilegeMapper;
import com.zimi.model.SysRole;
import com.zimi.model.SysRolePrivilege;
import com.zimi.model.SysUser;
import com.zimi.util.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 系统角色表 Service
 *
 * @author lnintr
 * @since 2019-05-16
 */
@Service
public class SysRoleService {

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysRolePrivilegeMapper sysRolePrivilegeMapper;

    public Object list(SysRole role, int page, int limit) {
        return role.selectPage(new Page<>(page, limit), new QueryWrapper<SysRole>().setEntity(role).lambda().eq(SysRole::getRoleState, role.getRoleState()).eq(SysRole::getFlag, 2).gt(SysRole::getId, 2).orderByAsc(SysRole::getRoleSort));
    }

    public Object allList() {
        return sysRoleMapper.selectList(new QueryWrapper<SysRole>().lambda().eq(SysRole::getRoleState, 1).eq(SysRole::getFlag, 2).gt(SysRole::getId, 2).orderByAsc(SysRole::getRoleSort));
    }

    public Object insert(SysRole role) {
        // 1）确认角色名是否已登录过
        SysRole result = role.selectOne(new QueryWrapper<SysRole>().lambda().eq(SysRole::getRoleName, role.getRoleName()));
        if (result != null) {
            throw new RuntimeException("角色名为别的角色已登录过，请改角色名再提交。");
        }

        SysUser user = UserUtil.getUser();

        role.setFlag(2);
        role.setRoleState(1);
        role.setCreateUser(user.getId());
        role.setCreateTime(new Date());

        role.insert();

        role.setRoleSort(role.getId());
        role.updateById();
        return role;
    }

    @Transactional
    public Object update(SysRole role) {
        // 1）确认角色名是否被别的数据已登录过
        SysRole result = role.selectOne(new QueryWrapper<SysRole>().lambda().eq(SysRole::getRoleName, role.getRoleName()));
        if (result != null && result.getId().intValue() != role.getId().intValue()) {
            throw new RuntimeException("角色名为别的角色已登录过，请改角色名再提交。");
        }

        // 1）对要修改的对象加行锁
        result = role.selectOne(new QueryWrapper<SysRole>().lambda().eq(SysRole::getId, role.getId()).last("for update"));

        // 2）判断该数据已经被改过没有
        if (result.getUpdateTime() != null) {
            if (role.getUpdateTime() == null) {
                throw new RuntimeException("修改数据失败，数据已经被其他用户改过。");
            } else {
                if (role.getUpdateTime().getTime() != result.getUpdateTime().getTime()) {
                    throw new RuntimeException("修改数据失败，数据已经被其他用户改过。");
                }
            }
        }

        SysUser user = UserUtil.getUser();

        result.setRoleName(role.getRoleName());
        result.setRoleRemark(role.getRoleRemark());
        result.setUpdateUser(user.getId());
        result.setRoleState(role.getRoleState());
        result.setUpdateTime(new Date());

        // 3)变更数据
        return result.updateById();
    }

    @Transactional
    public int recycle(List<SysRole> sysRoleList) {
        Map<Integer, SysRole> cateMap = new HashMap<>();
        // 2）对要修改的对象加行锁
        List<Integer> idList = new ArrayList<>();
        for (SysRole sr : sysRoleList) {
            cateMap.put(sr.getId(), sr);
            idList.add(sr.getId());
        }

        List<SysRole> result = sysRoleMapper.selectList(new QueryWrapper<SysRole>().lambda().in(SysRole::getId, idList).last("for update"));

        if (result != null && result.size() > 0) {
            SysRole tmpRole = null;

            SysUser user = UserUtil.getUser();
            Date updateTime = new Date();

            for (SysRole sr : result) {
                tmpRole = cateMap.get(sr.getId());

                // 3）判断该数据已经被改过没有
                if (sr.getUpdateTime() != null) {
                    if (tmpRole.getUpdateTime() == null) {
                        throw new RuntimeException("删除数据失败，数据已经被其他用户改过。");
                    } else {
                        if (sr.getUpdateTime().getTime() != tmpRole.getUpdateTime().getTime()) {
                            throw new RuntimeException("删除数据失败，数据已经被其他用户改过。");
                        }
                    }
                }
            }

            SysRole sysRole = new SysRole().setUpdateUser(user.getId()).setUpdateTime(updateTime).setRoleState(1);
            sysRoleMapper.update(sysRole, new UpdateWrapper<SysRole>().lambda().in(SysRole::getId, idList));

            // 所属权限一并恢复
            SysRolePrivilege sysRolePrivilege = new SysRolePrivilege().setUpdateUser(user.getId()).setUpdateTime(updateTime).setPrivilegeState(1);
            sysRolePrivilegeMapper.update(sysRolePrivilege, new UpdateWrapper<SysRolePrivilege>().lambda().in(SysRolePrivilege::getRoleId, idList));
        } else {
            throw new RuntimeException("删除数据失败，数据已经被其他用户改过。");
        }

        return 0;
    }

    @Transactional
    public int move(List<SysRole> sysRoleList) {
        Map<Integer, SysRole> roleMap = new HashMap<>();
        // 1）对要修改的对象数据数量进行验证
        if (sysRoleList.size() != 2) {
            throw new RuntimeException("提交的关于交换顺序的数据不正确。");
        }

        // 2）对要修改的对象加行锁
        List<Integer> idList = new ArrayList<>();
        for (SysRole sr : sysRoleList) {
            roleMap.put(sr.getId(), sr);
            idList.add(sr.getId());
        }

        List<SysRole> result = sysRoleMapper.selectList(new QueryWrapper<SysRole>().lambda().in(SysRole::getId, idList).last("for update"));

        if (result == null || result.size() != 2) {
            throw new RuntimeException("服务器关于交换顺序的数据异常。");
        }

        SysRole tmpRole = null;

        SysUser user = UserUtil.getUser();
        Date updateTime = new Date();

        for (SysRole sr : sysRoleList) {
            tmpRole = roleMap.get(sr.getId());

            // 3）判断该数据已经被改过没有
            if (sr.getUpdateTime() != null) {
                if (tmpRole.getUpdateTime() == null) {
                    throw new RuntimeException("删除数据失败，数据已经被其他用户改过。");
                } else {
                    if (sr.getUpdateTime().getTime() != tmpRole.getUpdateTime().getTime()) {
                        throw new RuntimeException("删除数据失败，数据已经被其他用户改过。");
                    }
                }
            }

            // 4)变更数据
            tmpRole.setUpdateUser(user.getId());
            tmpRole.setUpdateTime(updateTime);
            tmpRole.updateById();
        }

        return 0;
    }
}
